/*!
 * \file ice_core.c
 *
 * \brief 共通定义
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * 共通使用的宏和结构体
 *
 * \version 1.0
 * \author jikw
 * \date 2017/6/16
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "config.h"
#include "frct_comm.h"
#include "frreport_comm.h"
#include "frservice_comm.h"
#include "frbyte_buffer.h"
#include "iconv2utf8.h"
#include "ice_core.h"

extern void *g_p_apm_context;
extern pthread_spinlock_t g_ice_list_lock;  //全局哈希表的自旋锁
extern Frhash_header *p_ice_list;   //哈希表头存ice_data
struct timeval g_st_time;

typedef struct __st_ice_data
{
    L4_transaction st_l4_trans;                 //L4信息统计
    Frlist_header *p_report_comm;               //用于临时存储report的公共部分数据
    Frlist_header *p_report_req;                //用于临时存储report的请求部分数据
} ice_data;

typedef struct __st_L7session_ice_private
{
    unsigned long ul_seq;                       //序列号，1次req和response时，使用同一个序列号
    L4_transaction st_l4_trans;                 //数据
    Frreport_body_data *p_st_body_data_req;
    Frreport_body_data *p_st_body_data_resp;
    Frbyte_Packet *p_req_packet;                //存请求bytebuff数据
    Frbyte_Packet *p_resp_packet;               //存相应bytebuff数据
} L7session_ice_private;

/*!
 * ice私有数据创建
 *
 * \param void
 *
 * \return NULL          内存分配失败\n
 *         p_st_private  内存分配成功
 *
 * \note
 *
 */
FR_STATIC L7session_ice_private* __ice_private_create(void)
{
    L7session_ice_private *p_st_private = NULL;
    p_st_private = (L7session_ice_private*)frmalloc(sizeof(L7session_ice_private));
    if (p_st_private == NULL)
        return NULL;
    memset(p_st_private, 0x00, sizeof(L7session_ice_private));

    return p_st_private;
}

/*!
 * 私有信息重置
 *
 * \param p_private_session  (ice的私有session数据)
 *
 * \return FR_SUCC   成功\n
 *
 * \note
 *
 */
FR_STATIC int __ice_session_reset(void *p_private_session)
{
    L7session_ice_private *p_st_private = (L7session_ice_private*)p_private_session;

    if (p_st_private)
    {
        if (p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if (p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if (p_st_private->p_req_packet)
            bytebuff_free(&(p_st_private->p_req_packet));

        if (p_st_private->p_resp_packet)
            bytebuff_free(&(p_st_private->p_resp_packet));
    }
    return FR_SUCC;
}

/*!
 * 判断是否是ice协议
 *
 * \param p_st_conn      (输入数据信息)
 * \param p_st_packet    (输入数据)
 *
 * \return APM_L7_IS_YES  属于ice协议\n
 *         APM_L7_IS_NO   不属于ice协议
 *
 * \note
 *
 */
int ice_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet)
{
    int i_ret = 0;

    if (p_st_packet == NULL || p_st_packet->p_payload == NULL || p_st_packet->ui_payload_len < 14 || p_st_conn==NULL)
        return APM_L7_IS_NO;

    /*
    struct HeaderData
    {
        int magic;                  // 固定：IceP
        byte protocolMajor;         // 版本号
        byte protocolMinor;
        byte encodingMajor;
        byte encodingMinor;
        byte messageType;           // 消息类型
        byte compressionStatus;     // 压缩标记 0未压缩  1未压缩但可以接受压缩应答 2已压缩可以接受压缩应答
        int messageSize;            // 消息长度
    };
    */

    //magic
    if (memcmp(p_st_packet->p_payload, MAGIC, 4) != 0)
        goto ERROR;
    //compressionStatus
    if (*(p_st_packet->p_payload+9) != COMPRESSION0 &&
        *(p_st_packet->p_payload+9) != COMPRESSION1 &&
        *(p_st_packet->p_payload+9) != COMPRESSION2)
        goto ERROR;
    //messageSize

    i_ret = frct_get_direct_known(p_st_conn);
    if (i_ret == FR_DIRECT_UNKNOWN)
    {
        //根据messageType判断方向
        if (*(p_st_packet->p_payload+8) == MESSAGETYPE0 ||
            *(p_st_packet->p_payload+8) == MESSAGETYPE1 ||
            *(p_st_packet->p_payload+8) == MESSAGETYPE4)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
            frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);
        }
        else if (*(p_st_packet->p_payload+8) == MESSAGETYPE2 ||
            *(p_st_packet->p_payload+8) == MESSAGETYPE3)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
            frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0);
        }
        else
            goto ERROR;
    }

    return APM_L7_IS_YES;

ERROR:
    if (frct_get_direct_known(p_st_conn) == FR_DIRECT_UNKNOWN)
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
            return APM_L7_IS_YES;
        }
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
            return APM_L7_IS_YES;
        }
    }
    else
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
            return APM_L7_IS_YES;

        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
            return APM_L7_IS_YES;
    }
    return APM_L7_IS_NO;
}

/*!
 * 链表节点释放规则
 *
 * \Frlist_node *p_st_node
 *
 * \return void
 *
 * \note
 *
 */
void ice_list_node_free(Frlist_node *p_st_node)
{
    ice_data *p_st_info = NULL;

    if (p_st_node==NULL || p_st_node->data == NULL )
        return;

    p_st_info = (ice_data *)FRLIST_GET_NODE_DATA(p_st_node);

    if (p_st_info->p_report_req)
        frreport_body_l7list_free(&p_st_info->p_report_req);
    if (p_st_info->p_report_comm)
        frreport_body_l7list_free(&p_st_info->p_report_comm);

    frfree(p_st_info);
    return;
}

/*!
 * 取string(需要外部释放)
 *
 * \Frbyte_Packet *p_packete
 *
 * \return FR_SUCC
 *         FR_FAIL
 *
 * \note
 *
 */
FR_STATIC int __get_string(Frbyte_Packet *p_packet, char **pp_out)
{
    int i_string = 0;
    uint8_t u8_string_len = 0;
    uint32_t u32_string_len = 0;
    char *p_string = NULL;

    if (p_packet == NULL)
        return FR_FAIL;

    if (bytebuff_get_char(p_packet, &u8_string_len) == FR_FAIL)
        return FR_FAIL;
    if (u8_string_len == '\xFF')
    {
        if (bytebuff_get_int(p_packet, 4, &u32_string_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
            return FR_FAIL;
        i_string = u32_string_len;
    }
    else
        i_string = u8_string_len;

    p_string = (char *)frmalloc(i_string+1);
    if (p_string == NULL)
        goto ERROR;
    memset(p_string, 0x00, i_string+1);
    if (bytebuff_get_bytes(p_packet, p_string, i_string) == FR_FAIL)
        goto ERROR;
    *pp_out = p_string;

    return FR_SUCC;

ERROR:
    if (p_string)
        frfree(p_string);
    return FR_FAIL;
}

/*!
 * req数据解析
 *
 * \param p_packet        (req数据)
 * \param p_st_body_data
 * \param p_i_opaque      (取出的requestid)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __req_parse(Frbyte_Packet *p_packet
                        , Frreport_body_data *p_st_body_data
                        , int *p_requestid)
{
    int i_count = 0;
    int i_para_len = 0;
    uint8_t u8_type = 0;
    uint8_t u8_count = 0;
    uint8_t u8_operation_mode = 0;
    uint32_t u32_len = 0;
    uint32_t u32_requestid = 0;
    uint32_t u32_para_len = 0;
    char arr_temp[8];
    char arr_name[64];
    char arr_title[64];
    char *p_identity_name = NULL;
    char *p_identity_content = NULL;
    char *p_facet = NULL;
    char *p_operation = NULL;
    char *p_context_key = NULL;
    char *p_context_value = NULL;
    char *p_para = NULL;

    if (p_packet == NULL || p_st_body_data == NULL)
        return APM_L7_ANALYZE_FAIL;

    //解析header
    //magic
    if (bytebuff_get_bytes(p_packet, arr_temp, 4) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    arr_temp[4] = '\0';
    if (memcmp(arr_temp, MAGIC, 4) != 0)
        return APM_L7_ANALYZE_FAIL;
    //版本号
    if (bytebuff_skip(p_packet, 4) != FR_SUCC)
        return APM_L7_ANALYZE_FAIL;
    //消息类型
    if (bytebuff_get_char(p_packet, &u8_type) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //压缩标记
    if (bytebuff_skip(p_packet, 1) != FR_SUCC)
        return APM_L7_ANALYZE_FAIL;
    //消息长度
    if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (u32_len != p_packet->ui_all_len)
        return APM_L7_ANALYZE_TODO;

    //解析body
    //请求消息
    if (u8_type == MESSAGETYPE0)
    {
        if (frreport_body_l7_add_int(p_st_body_data, APM_REPORT_KEY_REQ_ISRESPREQUIRED, 1) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
        //请求序列号
        if (bytebuff_get_int(p_packet, 4, &u32_requestid, BYTE_LITTLE_ENDIAN) == FR_FAIL)
            goto ERROR;
        *p_requestid = u32_requestid;
        //对象标识名称
        if (__get_string(p_packet, &p_identity_name) == FR_FAIL)
            goto ERROR;
        if (frreport_body_l7_add_str(p_st_body_data, "request.ice.identity_name", p_identity_name) == FR_FAIL)
            goto ERROR;
        //对象标识内容
        if (__get_string(p_packet, &p_identity_content) == FR_FAIL)
            goto ERROR;
        if (frreport_body_l7_add_str(p_st_body_data, "request.ice.identity_content", p_identity_content) == FR_FAIL)
            goto ERROR;
        frfree(p_identity_content);
        //facet名称
        if (bytebuff_get_char(p_packet, &u8_count) == FR_FAIL)
            goto ERROR;
        if (u8_count == 0)
        {
            if (frreport_body_l7_add_str(p_st_body_data, "request.ice.facet", "") == FR_FAIL)
                goto ERROR;
        }
        for (i_count=0;i_count<u8_count;i_count++)
        {
            snprintf(arr_name, sizeof(arr_name), "request.ice.facet.%d", i_count+1);
            if (__get_string(p_packet, &p_facet) == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_facet) == FR_FAIL)
                goto ERROR;
            frfree(p_facet);
            p_facet = NULL;
        }
        //操作标示
        if (__get_string(p_packet, &p_operation) == FR_FAIL)
            goto ERROR;
        if (frreport_body_l7_add_str(p_st_body_data, "request.ice.operation", p_operation) == FR_FAIL)
            goto ERROR;

		if (memcmp(p_operation, "createSession", strlen(p_operation)) == 0)
		{
		    if (frreport_body_l7_add_str(p_st_body_data, "transaction.channel_code", "LOGIN") == FR_FAIL)
		        goto ERROR;
		    if (frreport_body_l7_add_str(p_st_body_data, "transaction.channel_name", "LOGIN") == FR_FAIL)
		        goto ERROR;
		    if (frreport_body_l7_add_str(p_st_body_data, "transaction.type_code", "LOGIN") == FR_FAIL)
		        goto ERROR;
		    if (frreport_body_l7_add_str(p_st_body_data, "transaction.type_name", "LOGIN") == FR_FAIL)
		        goto ERROR;
		}

        snprintf(arr_title, sizeof(arr_title), "%s.%s", p_identity_name, p_operation);
        if (frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, arr_title) == FR_FAIL)
            goto ERROR;
        frfree(p_identity_name);
        frfree(p_operation);
        //调用模式
        if (bytebuff_get_char(p_packet, &u8_operation_mode) == FR_FAIL)
            goto ERROR;
        switch(u8_operation_mode)
        {
            case 0x00:
                if (frreport_body_l7_add_str(p_st_body_data, "request.ice.operation_mode", "normal") == FR_FAIL)
                    goto ERROR;
                break;
            case 0x01:
                if (frreport_body_l7_add_str(p_st_body_data, "request.ice.operation_mode", "nonmutating") == FR_FAIL)
                    goto ERROR;
                break;
            case 0x02:
                if (frreport_body_l7_add_str(p_st_body_data, "request.ice.operation_mode", "idempotent") == FR_FAIL)
                    goto ERROR;
                break;
            default:
                goto ERROR;
        }
        //上下文
        if (bytebuff_get_char(p_packet, &u8_count) == FR_FAIL)
            goto ERROR;
        if (u8_count == 0)
        {
            if (frreport_body_l7_add_str(p_st_body_data, "request.ice.context", "") == FR_FAIL)
                goto ERROR;
        }
        for (i_count=0;i_count<u8_count;i_count++)
        {
            snprintf(arr_name, sizeof(arr_name), "request.ice.context.%d.key", i_count+1);
            if (__get_string(p_packet, &p_context_key) == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_context_key) == FR_FAIL)
                goto ERROR;
            snprintf(arr_name, sizeof(arr_name), "request.ice.context.%d.value", i_count+1);
            if (__get_string(p_packet, &p_context_value) == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_context_value) == FR_FAIL)
                goto ERROR;
            frfree(p_context_key);
            p_context_key = NULL;
            frfree(p_context_value);
            p_context_value = NULL;
        }
        //输入参数
        if (bytebuff_get_int(p_packet, 4, &u32_para_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
            goto ERROR;
        if (u32_para_len > 6)
        {
            if (bytebuff_skip(p_packet, 2) != FR_SUCC)
                goto ERROR;
            i_para_len = u32_para_len-6;
            p_para = (char *)frmalloc(i_para_len+1);
            if (p_para == NULL)
                goto ERROR;
            memset(p_para, 0x00, i_para_len+1);
            if (bytebuff_get_bytes(p_packet, p_para, i_para_len) == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_bin(p_st_body_data, "request.ice.para", p_para, i_para_len) == FR_FAIL)
                goto ERROR;
            frfree(p_para);
        }
        else
        {
            if (frreport_body_l7_add_str(p_st_body_data, "request.ice.para", "") == FR_FAIL)
                goto ERROR;
        }
    }
    //批量请求消息
    else if (u8_type == MESSAGETYPE1)
    {
        if (frreport_body_l7_add_int(p_st_body_data, APM_REPORT_KEY_REQ_ISRESPREQUIRED, 0) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
        //对象标识名称
        if (__get_string(p_packet, &p_identity_name) == FR_FAIL)
            goto ERROR;
        if (frreport_body_l7_add_str(p_st_body_data, "request.ice.identity_name", p_identity_name) == FR_FAIL)
            goto ERROR;
        //对象标识内容
        if (__get_string(p_packet, &p_identity_content) == FR_FAIL)
            goto ERROR;
        if (frreport_body_l7_add_str(p_st_body_data, "request.ice.identity_content", p_identity_content) == FR_FAIL)
            goto ERROR;
        frfree(p_identity_content);
        //facet名称
        if (bytebuff_get_char(p_packet, &u8_count) == FR_FAIL)
            goto ERROR;
        if (u8_count == 0)
        {
            if (frreport_body_l7_add_str(p_st_body_data, "request.ice.facet", "") == FR_FAIL)
                goto ERROR;
        }
        for (i_count=0;i_count<u8_count;i_count++)
        {
            snprintf(arr_name, sizeof(arr_name), "request.ice.facet.%d", i_count+1);
            if (__get_string(p_packet, &p_facet) == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_facet) == FR_FAIL)
                goto ERROR;
            frfree(p_facet);
            p_facet = NULL;
        }
        //操作标示
        if (__get_string(p_packet, &p_operation) == FR_FAIL)
            goto ERROR;
        if (frreport_body_l7_add_str(p_st_body_data, "request.ice.operation", p_operation) == FR_FAIL)
            goto ERROR;

        snprintf(arr_title, sizeof(arr_title), "%s.%s", p_identity_name, p_operation);
        if (frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, arr_title) == FR_FAIL)
            goto ERROR;
        frfree(p_identity_name);
        frfree(p_operation);
        //调用模式
        if (bytebuff_get_char(p_packet, &u8_operation_mode) == FR_FAIL)
            goto ERROR;
        switch(u8_operation_mode)
        {
            case 0x00:
                if (frreport_body_l7_add_str(p_st_body_data, "request.ice.operation_mode", "normal") == FR_FAIL)
                    goto ERROR;
                break;
            case 0x01:
                if (frreport_body_l7_add_str(p_st_body_data, "request.ice.operation_mode", "nonmutating") == FR_FAIL)
                    goto ERROR;
                break;
            case 0x02:
                if (frreport_body_l7_add_str(p_st_body_data, "request.ice.operation_mode", "idempotent") == FR_FAIL)
                    goto ERROR;
                break;
            default:
                goto ERROR;
        }
        //上下文
        if (bytebuff_get_char(p_packet, &u8_count) == FR_FAIL)
            goto ERROR;
        if (u8_count == 0)
        {
            if (frreport_body_l7_add_str(p_st_body_data, "request.ice.context", "") == FR_FAIL)
                goto ERROR;
        }
        for (i_count=0;i_count<u8_count;i_count++)
        {
            snprintf(arr_name, sizeof(arr_name), "request.ice.context.%d.key", i_count+1);
            if (__get_string(p_packet, &p_context_key) == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_context_key) == FR_FAIL)
                goto ERROR;
            snprintf(arr_name, sizeof(arr_name), "request.ice.context.%d.value", i_count+1);
            if (__get_string(p_packet, &p_context_value) == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_context_value) == FR_FAIL)
                goto ERROR;
            frfree(p_context_key);
            p_context_key = NULL;
            frfree(p_context_value);
            p_context_value = NULL;
        }
        //输入参数
        if (bytebuff_get_int(p_packet, 4, &u32_para_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
            goto ERROR;
        if (u32_para_len > 6)
        {
            if (bytebuff_skip(p_packet, 2) != FR_SUCC)
                goto ERROR;
            i_para_len = u32_para_len-6;
            p_para = (char *)frmalloc(i_para_len+1);
            if (p_para == NULL)
                goto ERROR;
            memset(p_para, 0x00, i_para_len+1);
            if (bytebuff_get_bytes(p_packet, p_para, i_para_len) == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_bin(p_st_body_data, "request.ice.para", p_para, i_para_len) == FR_FAIL)
                goto ERROR;
            frfree(p_para);
        }
        else
        {
            if (frreport_body_l7_add_str(p_st_body_data, "request.ice.para", "") == FR_FAIL)
                goto ERROR;
        }
    }
    //关闭连接消息
    else if (u8_type == MESSAGETYPE4)
    {
        if (frreport_body_l7_add_int(p_st_body_data, APM_REPORT_KEY_REQ_ISRESPREQUIRED, 0) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
    }
    else
        return APM_L7_ANALYZE_FAIL;

    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);

ERROR:
    if (p_identity_name)
        frfree(p_identity_name);
    if (p_identity_content)
        frfree(p_identity_content);
    if (p_facet)
        frfree(p_facet);
    if (p_operation)
        frfree(p_operation);
    if (p_context_key)
        frfree(p_context_key);
    if (p_context_value)
        frfree(p_context_value);
    if (p_para)
        frfree(p_para);
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * resp数据解析
 *
 * \param p_packet        (resp数据)
 * \param p_st_body_data
 * \param requestid       (requestid)
 *
 * \return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC)   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __resp_parse(Frbyte_Packet *p_packet
                         , Frreport_body_data *p_st_body_data
                         , int *p_requestid)
{
    uint8_t u8_type = 0;
    uint8_t u8_replystatus = 0;
    uint32_t u32_len = 0;
    uint32_t u32_requestid = 0;
    int i_body = 0;
    char arr_temp[8];
    char *p_body = NULL;

    if (p_packet == NULL || p_st_body_data == NULL)
        return APM_L7_ANALYZE_FAIL;

    //解析header
    //magic
    if (bytebuff_get_bytes(p_packet, arr_temp, 4) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    arr_temp[4] = '\0';
    if (memcmp(arr_temp, MAGIC, 4) != 0)
        return APM_L7_ANALYZE_FAIL;
    //版本号
    if (bytebuff_skip(p_packet, 4) != FR_SUCC)
        return APM_L7_ANALYZE_FAIL;
    //消息类型
    if (bytebuff_get_char(p_packet, &u8_type) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //压缩标记
    if (bytebuff_skip(p_packet, 1) != FR_SUCC)
        return APM_L7_ANALYZE_FAIL;
    //消息长度
    if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (u32_len != p_packet->ui_all_len)
        return APM_L7_ANALYZE_TODO;

    //解析body
    //应答消息
    if (u8_type == MESSAGETYPE2)
    {
        //请求序列号TODO
        if (bytebuff_get_int(p_packet, 4, &u32_requestid, BYTE_LITTLE_ENDIAN) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
        *p_requestid = u32_requestid;
        //replyStatus
        if (bytebuff_get_char(p_packet, &u8_replystatus) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
        if (frreport_body_l7_add_int(p_st_body_data, "response.code", u8_replystatus) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
        switch(u8_replystatus)
        {
            case 0x00:
                if (frreport_body_l7_add_str(p_st_body_data, "response.error_message", "成功") == FR_FAIL)
                    return APM_L7_ANALYZE_FAIL;
                break;
            case 0x01:
                if (frreport_body_l7_add_str(p_st_body_data, "response.error_message", "用户异常") == FR_FAIL)
                    return APM_L7_ANALYZE_FAIL;
                break;
            case 0x02:
                if (frreport_body_l7_add_str(p_st_body_data, "response.error_message", "对象不存在") == FR_FAIL)
                    return APM_L7_ANALYZE_FAIL;
                break;
            case 0x03:
                if (frreport_body_l7_add_str(p_st_body_data, "response.error_message", "facet不存在") == FR_FAIL)
                    return APM_L7_ANALYZE_FAIL;
                break;
            case 0x04:
                if (frreport_body_l7_add_str(p_st_body_data, "response.error_message", "操作不存在") == FR_FAIL)
                    return APM_L7_ANALYZE_FAIL;
                break;
            case 0x05:
                if (frreport_body_l7_add_str(p_st_body_data, "response.error_message", "未知本地异常") == FR_FAIL)
                    return APM_L7_ANALYZE_FAIL;
                break;
            case 0x06:
                if (frreport_body_l7_add_str(p_st_body_data, "response.error_message", "未知用户异常") == FR_FAIL)
                    return APM_L7_ANALYZE_FAIL;
                break;
            case 0x07:
                if (frreport_body_l7_add_str(p_st_body_data, "response.error_message", "未知异常") == FR_FAIL)
                    return APM_L7_ANALYZE_FAIL;
                break;
            default:
                goto ERROR;
        }
        //body
        i_body = p_packet->ui_remaining;
        p_body = (char *)frmalloc(i_body+1);
        if (p_body == NULL)
            goto ERROR;
        memset(p_body, 0x00, i_body+1);
        if (bytebuff_get_bytes(p_packet, p_body, i_body) == FR_FAIL)
            goto ERROR;
        if (frreport_body_l7_add_bin(p_st_body_data, "response.ice.body", p_body, i_body) == FR_FAIL)
            goto ERROR;
        frfree(p_body);
    }
    //验证连接消息
    else if (u8_type == MESSAGETYPE3)
    {
    	return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);
    }
    else
        return APM_L7_ANALYZE_FAIL;

    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);

ERROR:
    if (p_body)
        frfree(p_body);
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * req的p_report_comm、p_report_req、L4信息和ID存进链表
 *
 * \param p_st_private    (ice私有数据)
 * \param i_requestid     (requestid)
 *
 * \return FR_FAIL        失败\n
 *         FR_SUCC        成功
 *
 * \note
 *
 */
FR_STATIC int __ice_add_req_list(L7session_ice_private *p_st_private, int i_requestid)
{
    ice_data *p_st_report = NULL;
	Frlist_node *p_st_node = NULL;
	Frlist_node *p_st_gotnode = NULL;
	L4_transaction *p_st_l4_trans = NULL;

    if (p_st_private == NULL)
        return FR_FAIL;

    p_st_l4_trans = &(p_st_private->st_l4_trans);

    //req的p_report_comm、p_report_req、L4信息和ID存进链表
    p_st_report = (ice_data *)frmalloc(sizeof(ice_data));
    memset(p_st_report, 0x00, sizeof(ice_data));

    //拷贝L4信息统计
    memcpy(&p_st_report->st_l4_trans, p_st_l4_trans, sizeof(L4_transaction));
    //拷贝相关链表
    p_st_report->p_report_comm = FRREPORT_BODY_L7LIST_CLONE_COMM(p_st_private->p_st_body_data_req);
    if (p_st_report->p_report_comm == NULL)
        goto ERROR;
    p_st_report->p_report_req = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_private->p_st_body_data_req);
    if (p_st_report->p_report_req == NULL)
        goto ERROR;

    p_st_node = frlist_node_create(p_st_report);
    //存list之前 判断key值(requestid)是否存在 如存在删除节点 再加节点
    pthread_spin_lock(&g_ice_list_lock);
    p_st_gotnode = frhash2_getLong(p_ice_list, i_requestid);
    if (p_st_gotnode != NULL)
    {
        frhash2_del(p_ice_list, p_st_gotnode, ice_list_node_free);
        p_st_gotnode = NULL;
    }
    frhash2_addLong(p_ice_list, i_requestid, p_st_node);
    pthread_spin_unlock(&g_ice_list_lock);

    return FR_SUCC;

ERROR:
    if (p_st_report)
        frfree(p_st_report);
    if (p_st_report->p_report_comm)
        frreport_body_l7list_free(&p_st_report->p_report_comm);
    if (p_st_report->p_report_req)
        frreport_body_l7list_free(&p_st_report->p_report_req);
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * 检查是否超时
 *
 * \param p_node
 * \param p_data
 *
 * \return int
 *
 * \note
 *
 */
FR_STATIC int __check_timeout(Frlist_node* p_node, const void *p_data)
{
    ice_data *p_st_info = NULL;
    Frhash_header *p_header = (Frhash_header *)p_data;

    p_st_info = (ice_data *)p_node->data;

    if (p_st_info->st_l4_trans.st_request_time.tv_sec + ICE_TIMEOUT <= g_st_time.tv_sec)
    {
        frhash2_del(p_header, p_node, ice_list_node_free);
        return 1;
    }

    return 1;
}

/*!
 * 清除hash中超时的node
 *
 * \param p_hash_stmt
 * \param st_timestamp
 *
 * \return int
 *
 * \note
 *
 */
FR_STATIC void __clear_timeout_node(Frhash_header *p_header, struct timeval st_timestamp)
{
    g_st_time = st_timestamp;
    frhash2_run(p_header, p_header, __check_timeout);

    return;
}

/*!
 * ice的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *         APM_L7_ANALYZE_TODO
 *
 * \note
 *
 */
FR_STATIC int __req_data_analysis(Conntrack *p_st_conn
                                , Apm_packet *p_st_packet
                                , Frhash_header *p_st_hash_report
                                , L7_session *p_st_session)
{
	uint32_t u32_len = 0;
    int i_ret = 0;
    unsigned long ul_tmp = 0;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data *p_st_report_data = NULL;
    L7session_ice_private *p_st_private = NULL;
    int i_requestid = 0;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_ice_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    //创建数据链表
    if (p_st_private->p_st_body_data_req == NULL)
    {
        p_st_private->p_st_body_data_req = frreport_body_new_l7(p_st_conn);
        if (p_st_private->p_st_body_data_req == NULL)
            goto ERROR;

        if (frreport_body_l7_add_connInfo(p_st_private->p_st_body_data_req, p_st_conn) == FR_FAIL)
            goto ERROR;

        //seq ++
        p_st_private->ul_seq = frct_seq_increase(p_st_conn);

        if (p_st_l4_trans->st_request_time_first_byte.tv_sec==0 && p_st_l4_trans->st_request_time_first_byte.tv_usec==0)
        {
            //st_request_time_first_byte
            p_st_l4_trans->st_request_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_l4_trans->st_request_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
        }

        //创建bytebuff
        if (p_st_private->p_req_packet == NULL)
        {
            p_st_private->p_req_packet = bytebuff_creat();
            if (p_st_private->p_req_packet == NULL)
                goto ERROR;
        }
    }
    //请求的字节数
    p_st_l4_trans->l_request_bytes += p_st_packet->ui_payload_len;

    if (p_st_private->p_req_packet == NULL)
        goto ERROR;

    //把这个包的数据先全加进bytebuff里
    if (bytebuff_add(p_st_private->p_req_packet, p_st_packet->p_payload, p_st_packet->ui_payload_len) != FR_SUCC)
        goto ERROR;

    if (bytebuff_skip(p_st_private->p_req_packet, 10) != FR_SUCC)
        goto ERROR;
    if (bytebuff_get_int(p_st_private->p_req_packet, 4, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
        goto ERROR;
    if (u32_len > p_st_private->p_req_packet->ui_all_len)
    {
        bytebuff_rewind(p_st_private->p_req_packet);
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_rewind(p_st_private->p_req_packet);

    //req解析
    i_ret = __req_parse(p_st_private->p_req_packet, p_st_private->p_st_body_data_req, &i_requestid);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        goto ERROR;

    if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_ID, p_st_private->ul_seq) == FR_FAIL)
        goto ERROR;

    //start time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_START_TIMESTAMP, &p_st_l4_trans->st_request_time_first_byte) == FR_FAIL)
        goto ERROR;

    //st_request_time
    p_st_l4_trans->st_request_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_request_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    ul_tmp = frtime_diff(&(p_st_l4_trans->st_request_time_first_byte), &(p_st_l4_trans->st_request_time));
    //send_time_us
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_SEND_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //request bytes
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_DATA_BYTES, p_st_l4_trans->l_request_bytes) == FR_FAIL)
        goto ERROR;

    //end time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_END_TIMESTAMP, &p_st_l4_trans->st_request_time) == FR_FAIL)
        goto ERROR;

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_REQ);
    if (p_st_report_data == NULL)
        goto ERROR;

	//isrequired req信息存链表
	if (i_requestid != 0)
	{
	    if (__ice_add_req_list(p_st_private, i_requestid) == FR_FAIL)
	        goto ERROR;
	}

    pthread_spin_lock(&g_ice_list_lock);
    __clear_timeout_node(p_ice_list, p_st_packet->st_timestamp);
    pthread_spin_unlock(&g_ice_list_lock);

    if (frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_req) == FR_FAIL)
        goto ERROR;
    p_st_private->p_st_body_data_req = NULL;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;
    p_st_report_data = NULL;

    __ice_session_reset((void *)(p_st_private));

    return i_ret;

ERROR:
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);
    __ice_session_reset((void *)(p_st_private));
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * ice的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *         APM_L7_ANALYZE_TODO
 *
 * \note
 *
 */
FR_STATIC int __resp_data_analysis(Conntrack *p_st_conn
                                 , Apm_packet *p_st_packet
                                 , Frhash_header *p_st_hash_report
                                 , L7_session *p_st_session)
{
	uint32_t u32_len = 0;
    int i_ret = 0;
    unsigned long ul_tmp = 0;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data* p_st_report_data = NULL;
    L7session_ice_private *p_st_private = NULL;
    int i_requestid = 0;
    Frlist_node *p_st_node = NULL;
    ice_data *p_st_data = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_ice_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    if (p_st_private->p_st_body_data_resp == NULL)
    {
        //创建数据链表
        p_st_private->p_st_body_data_resp = frreport_body_new_l7(p_st_conn);
        if (p_st_private->p_st_body_data_resp == NULL)
            goto ERROR;

        if (p_st_l4_trans->st_response_time_first_byte.tv_sec == 0 && p_st_l4_trans->st_response_time_first_byte.tv_usec == 0)
        {
            p_st_l4_trans->st_response_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_l4_trans->st_response_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
        }

        //创建bytebuff
        if (p_st_private->p_resp_packet == NULL)
        {
            p_st_private->p_resp_packet = bytebuff_creat();
            if (p_st_private->p_resp_packet == NULL)
                goto ERROR;
        }
    }

    //请求的字节数
    p_st_l4_trans->l_response_bytes += p_st_packet->ui_payload_len;

    if (p_st_private->p_resp_packet == NULL)
        goto ERROR;

    if (bytebuff_add(p_st_private->p_resp_packet, p_st_packet->p_payload, p_st_packet->ui_payload_len) != FR_SUCC)
        goto ERROR;

    if (bytebuff_skip(p_st_private->p_resp_packet, 10) != FR_SUCC)
        goto ERROR;
    if (bytebuff_get_int(p_st_private->p_resp_packet, 4, &u32_len, BYTE_LITTLE_ENDIAN) == FR_FAIL)
        goto ERROR;
    if (u32_len > p_st_private->p_resp_packet->ui_all_len)
    {
        bytebuff_rewind(p_st_private->p_resp_packet);
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_rewind(p_st_private->p_resp_packet);

    //resp解析
    i_ret = __resp_parse(p_st_private->p_resp_packet, p_st_private->p_st_body_data_resp, &i_requestid);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        goto ERROR;

	if (i_requestid != 0)
	{
	    //取链表对应的request p_report_req p_report_comm
	    pthread_spin_lock(&g_ice_list_lock);
	    p_st_node = frhash2_getLong(p_ice_list, i_requestid);
	    pthread_spin_unlock(&g_ice_list_lock);
	    if (p_st_node == NULL)
	        goto ERROR;
	    p_st_data = (ice_data *)p_st_node->data;
	    //数据上报
	    FRREPORT_BODY_L7LIST_SET_REQ(p_st_private->p_st_body_data_resp, &p_st_data->p_report_req);
	    FRREPORT_BODY_L7LIST_SET_COMM(p_st_private->p_st_body_data_resp, &p_st_data->p_report_comm);

	    //server time
	    ul_tmp = frtime_diff(&p_st_data->st_l4_trans.st_request_time, &(p_st_l4_trans->st_response_time_first_byte));
	    pthread_spin_lock(&g_ice_list_lock);
	    frhash2_del(p_ice_list, p_st_node, ice_list_node_free);
	    pthread_spin_unlock(&g_ice_list_lock);
	    if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, ul_tmp) == FR_FAIL)
	        goto ERROR;

	}

    //start time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_START_TIMESTAMP, &p_st_l4_trans->st_response_time_first_byte) == FR_FAIL)
        goto ERROR;

    //st_response_time
    p_st_l4_trans->st_response_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_response_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DATA_BYTES, p_st_l4_trans->l_response_bytes) == FR_FAIL)
        goto ERROR;

    //down load time
    ul_tmp = frtime_diff(&(p_st_l4_trans->st_response_time_first_byte), &(p_st_l4_trans->st_response_time));
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //end time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_END_TIMESTAMP, &p_st_l4_trans->st_response_time) == FR_FAIL)
        goto ERROR;

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_RESP);
    if (p_st_report_data == NULL)
        goto ERROR;

    if (frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_resp) == FR_FAIL)
        goto ERROR;
    p_st_private->p_st_body_data_resp = NULL;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;
    p_st_report_data = NULL;

    ice_session_destroy(p_st_session->p_session_private);
    p_st_session->p_session_private = NULL;

    return i_ret;

ERROR:
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);
    __ice_session_reset((void *)(p_st_private));
    frfree(p_st_private);
    p_st_session->p_session_private = NULL;
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * ice的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
int ice_analysis(Conntrack *p_st_conn
                           , Apm_packet *p_st_packet
                           , Frhash_header *p_st_hash_report)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_session *p_st_session = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    //到Conntrack中取得session信息
    p_st_session = frct_get_session(p_st_conn);
    if (p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    //fin、syn包销毁私有数据
    if (p_st_packet->em_analyz_cmd == FRANALYZ_CMD_FIN || p_st_packet->em_analyz_cmd == FRANALYZ_CMD_SYN)
    {
        ice_session_destroy(p_st_session->p_session_private);
        p_st_session->p_session_private = NULL;
        return APM_L7_ANALYZE_SUCC;
    }

    //p_session_private分配内存
    if (p_st_session->p_session_private == NULL)
    {
        p_st_session->p_session_private = __ice_private_create();
        //内存分配失败
        if (p_st_session->p_session_private == NULL)
            return APM_L7_ANALYZE_FAIL;
    }

    //request
    if (p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV)
    {
        i_ret = __req_data_analysis(p_st_conn, p_st_packet, p_st_hash_report, p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;
        return i_ret;
    }
    //response
    else
    {
        i_ret = __resp_data_analysis(p_st_conn, p_st_packet, p_st_hash_report, p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;
        return i_ret;
    }

ERROR:
    ice_session_destroy(p_st_session->p_session_private);
    p_st_session->p_session_private = NULL;
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * 私有信息销毁
 *
 * \param p_private_session  (ice的私有session数据)
 *
 * \return FR_SUCC   成功\n
 *
 * \note
 *
 */
int ice_session_destroy(void *p_private_session)
{
    L7session_ice_private *p_st_private = (L7session_ice_private*)p_private_session;

    if (p_st_private)
    {
        if (p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if (p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if (p_st_private->p_req_packet)
            bytebuff_free(&(p_st_private->p_req_packet));

        if (p_st_private->p_resp_packet)
            bytebuff_free(&(p_st_private->p_resp_packet));

        frfree(p_st_private);
    }

    return FR_SUCC;
}
